from transitions import Machine
from datetime import datetime
import time

class Phone:
    states = ['Normal', 'Locked', 'Unlocked']

    def __init__(self):
        self.machine = Machine(model=self, states=Phone.states, initial='Normal')

        # 锁定，条件：输错3次， 附带操作：清除错误次数、记录当前时间
        self.machine.add_transition('Lock', 'Normal', 'Locked',
                                    conditions=['error_3_times'],
                                    after='error_clear')
        # 输入, 附带操作：错误次数增加
        self.machine.add_transition('Input', 'Normal', 'Normal', unless='pwd_check', after='fresh_time')
        # 恢复
        self.machine.add_transition('Recover', 'Locked', 'Normal', conditions=['wait_enough'], after='error_clear')

        self.machine.add_transition('Open', 'Normal', 'Unlocked', conditions=['pwd_check'], after='error_clear')
        self.last_time = datetime.now()
        self.cnt = 0    # 记录输入次数
        self.password = ''

    # 清除错误次数，并且进入记录当前时间
    def error_clear(self):
        self.cnt = 0
        self.last_time = datetime.now()

    def fresh_time(self):
        self.last_time = datetime.now()

    def error_3_times(self):
        return self.cnt >= 3

    def wait_enough(self):
        return (datetime.now() - self.last_time).seconds >= 120

    def pwd_check(self):
        return self.password == '123456'

    def set_password(self, pwd):
        self.password = pwd
        self.cnt += 1


if __name__ == '__main__':
    p = Phone()
    print('---初始化---')
    print(f'当前输入{p.cnt}次，当前状态为：{p.state}')

    # 连续错误输入3次
    print('---输入---')
    p.set_password('147')
    p.Input()
    print(f'当前输入{p.cnt}次，当前状态为：{p.state}')
    print('---输入---')
    p.set_password('258')
    p.Input()
    print(f'当前输入{p.cnt}次，当前状态为：{p.state}')
    print('---输入---')
    p.set_password('258')
    p.Lock()
    print(f'当前输入{p.cnt}次，当前状态为：{p.state}')

    # 尝试再次输入
    print('等待时间尝试输入')
    try:
        p.Input()
    except:
        print(f'当前状态为：{p.state},不符合状态转移条件')
    print(f'当前状态为：{p.state}, 等待时间满足？{p.wait_enough()}')

    time.sleep(120)
    p.Recover()
    print(f'当前状态为：{p.state}')
    p.set_password('123456')
    p.Open()
    print(f'当前状态为：{p.state}')